//============================================================================
// Name        : sin_path.cpp
// Author      : dfoelber
//============================================================================

// INCLUDES //
#include "physics/sin_path.h"
#include <math.h>
#include <iostream>
//////////////

using namespace std;

/**
* Constructor
* 
* @param originX The origin's X coordinate
* @param originY The origin's Y coordinate
* @param destX The destination's X coordinate
* @param destY The destination's Y coordinate
* @param apexX The apex's X coordinate
* @param apexY The apex's Y coordinate
* @param vel Velocity of the path
**/
SinPath::SinPath( int originX, int originY, int destX, int destY, int apexX, int apexY, double vel ) :
	Path(),
	velocity(vel),
	originX(originX),
	originY(originY),
	destX(destX),
	destY(destY),
	apexX(apexX),
	apexY(apexY)
{
}

/**
* Lets the path know that time has passed and to move accordingly.
* 
* Overridden from Path.
* 
* @param ms The time passed since last called
**/
void SinPath::TimePassed( int ms )
{
	double distance = ((double)ms / 40.0) * velocity;
	
	double x = GetX(), y = GetY();
	CalculateCoordinates(GetX(), GetY(), distance, &x, &y);
	
	xDistance = x - GetX();
	yDistance = y - GetY();
	
	double moveX = 0.0, moveY = 0.0;
	x = y = 0.0;
	CalculateCoordinates(GetX(), GetY(), (destX - originX) / 20, &x, &y);
	moveX = x - GetX();
	moveY = y - GetY();
	
	if( moveX > 0 && moveY == 0 )
	{
		SetRotation(0);
	}
	if( moveX > 0 && moveY < 0 )
	{
		moveY *= -1;		
		double distance = sqrt( moveX * moveX + moveY * moveY );
		SetRotation( (int)((asin(moveY / distance) * (180 / M_PI))) );
	}
	else if( xDistance > 0 && yDistance > 0 )
	{	
		double distance = sqrt( moveX * moveX + moveY * moveY );
		SetRotation( 360 - (int)((asin(moveY / distance) * (180 / M_PI))) );		
	}
}

/**
* Check if this path collided with another path.
* 
* Overridden from Path.
* 
* @param other The other path.
**/
void SinPath::CheckCollision( Path* other )
{
	/*if( (int)(side & SIDE_LEFT) > 0 )
	{
		xDistance = other->GetX() + other->GetWidth() - GetX();
	}
	else if( (int)(side & SIDE_RIGHT) > 0 )
	{
		xDistance = other->GetX() - (GetX() + GetWidth());
	}
	else if( (int)(side & SIDE_BOTTOM) > 0 )
	{
		yDistance = other->GetY() - (GetY() + GetHeight()); 
	}
	else if( (int)(side & SIDE_TOP) > 0 )
	{
		yDistance = other->GetY() + other->GetHeight() - GetY();
	}
	
	length = 0;*/
}

/**
* Gets if the path is still moving.
* 
* Overridden from Path.
* 
* @return If the path is moving
**/
bool SinPath::IsMoving()
{
	return (GetX() != destX) || (GetY() != destY);
}

void SinPath::CalculateCoordinates( double x, double y, double distance, double* newX, double* newY )
{
	if( destX > originX && x < destX && destX != originX )
	{
		if( x < apexX && x + distance >= apexX )
		{
			// for now
			*newX = apexX;
			*newY = apexY;
		}
		else if( x + distance >= destX )
		{
			*newX = destX;
			*newY = destY;
		}
		else
		{
			int usedY = x < apexX ? originY : destY;
			
			double percentHeight = 0;
			if( x < apexX )
			{
				percentHeight = sin(((double)(x + distance - originX) / (double)((apexX - originX) * 2)) * M_PI);
			}
			else
			{
				percentHeight = cos(((double)(x + distance - apexX) / (double)(destX - apexX)) * M_PI / 2);
			}
			
			double newHeight = usedY + ((double)(apexY - usedY) * percentHeight);
			
			*newY = newHeight;
			*newX = x + distance;
		}
	}
}
